Аккаунт Google
Андрей Сапожников
sand.developer@gmail.com
Код
Вставить кодовую ячейку ниже
⌘/Ctrl+M B
Текст
Добавить текстовую ячейку
Показать/скрыть заголовок

Майнор "Интеллектуальный анализ данных"


Курс "Введение в анализ данных"

Код Текст

Лабораторная работа №3. Supervised Learning


Данные

Код Текст

В рамках данной лабораторной работы вам предлагается проанализировать набор данных о студентах двух школ в Португалии.
В файле students_data.csv представлена информация о студентах, посещающих два курса - математику (Math) и поргутальский язык (Por). Некоторые студенты представлены в обоих курсах, некоторые - только в одном. Для каждого студента известны три оценки по курсу: оценка за первое полугодие (G1), оценка за второе полугодие (G2) и итоговая оценка за год (G3).

Код Текст

Requirement already satisfied: graphviz in /usr/local/lib/python3.7/dist-packages (0.10.1)
Requirement already satisfied: wand in /usr/local/lib/python3.7/dist-packages (0.6.6)
Reading package lists... Done
Building dependency tree       
Reading state information... Done
libmagickwand-dev is already the newest version (8:6.9.7.4+dfsg-16ubuntu6.9).
0 upgraded, 0 newly installed, 0 to remove and 39 not upgraded.
Requirement already satisfied: xgboost in /usr/local/lib/python3.7/dist-packages (0.90)
Requirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from xgboost) (1.19.5)
Requirement already satisfied: scipy in /usr/local/lib/python3.7/dist-packages (from xgboost) (1.4.1)
Код Текст



Код Текст


(1044, 36)


Признаки


Данные представлены признаками различных типов: числовыми, категориальными, упорядоченными категориальными.


Описание признаков:



Часть 1. Предобработка данных


  • Разделите данные на две части - данные для моделирования (80%) и отложенную выборку (20%). Убедитесь, что распределение целевой переменной (G3) одинаково в обоих частях.
    NB: Отложенную выборку нужно использовать только для финальной оценки качества модели. Обучение и кросс-валидацию следует проводить на данных для моделирования.
  • Выполните необходимые преобразования данных: исправление ошибок, удаление выбросов и пропусков, приведение признаков к числовому виду.
  • Оцените значимость признаков для определения итоговой оценки за курс. Исключите из выборки незначимые на ваш взгляд признаки, обоснуйте свое решение.
  • (Опционально) Feature engineering: создайте новые признаки (значимые) на основе уже имеющихся.

Tip: Используйте свои наработки из Лабораторной работы №1.


Преобразование данных


Проверить на ошибочные значения


Key         Item
----------  ---------------------------------------------------------------------
Subject     ({'Math', 'Por'}, 2)
school      ({'MS', 'GP'}, 2)
sex         ({'m', 'F', 'M'}, 3)
address     ({'U', 'R'}, 2)
famsize     ({'GT3', 'LE3'}, 2)
Pstatus     ({'t', 'A', 'T'}, 3)
Medu        ({'1', '3', '2', 'o', '4', '0'}, 6)
Fedu        ({'1', '3', '2', 'o', '4', '0'}, 6)
Mjob        ({'services', 'teacher', 'at-home', 'other', 'health', 'at_home'}, 6)
Fjob        ({'services', 'teacher', 'at-home', 'other', 'health', 'at_home'}, 6)
reason      ({'reputation', 'other', 'home', 'course'}, 4)
guardian    ({'futher', 'other', 'mother', 'father'}, 4)
schoolsup   ({'yes', 'no'}, 2)
famsup      ({'yes', 'no'}, 2)
paid        ({'yes', 'no'}, 2)
activities  ({'yes', 'no'}, 2)
nursery     ({'yes', 'no'}, 2)
higher      ({'yes', 'no'}, 2)
internet    ({'yes', 'no'}, 2)
romantic    ({nan, 'yes', 'no'}, 3)
cheating    ({nan, 'yes', 'no'}, 3)

Key         Item
----------  ----------------------------------------------------------
Subject     ({'Math', 'Por'}, 2)
school      ({'MS', 'GP'}, 2)
sex         ({'F', 'M'}, 2)
address     ({'U', 'R'}, 2)
famsize     ({'GT3', 'LE3'}, 2)
Pstatus     ({'A', 'T'}, 2)
Medu        ({'1', '3', '2', '4', '0'}, 5)
Fedu        ({'1', '3', '2', '4', '0'}, 5)
Mjob        ({'services', 'teacher', 'other', 'health', 'at_home'}, 5)
Fjob        ({'services', 'teacher', 'other', 'health', 'at_home'}, 5)
reason      ({'reputation', 'other', 'home', 'course'}, 4)
guardian    ({'other', 'mother', 'father'}, 3)
schoolsup   ({'yes', 'no'}, 2)
famsup      ({'yes', 'no'}, 2)
paid        ({'yes', 'no'}, 2)
activities  ({'yes', 'no'}, 2)
nursery     ({'yes', 'no'}, 2)
higher      ({'yes', 'no'}, 2)
internet    ({'yes', 'no'}, 2)
romantic    ({nan, 'yes', 'no'}, 3)
cheating    ({nan, 'yes', 'no'}, 3)

Medu: int64 , Fedu: int64

Проверить на пропущенные значения


romantic     10
famrel       10
Dalc         10
Walc         10
cheating    700
dtype: int64
Код Текст

no     664
yes    370
NaN     10
Name: romantic, dtype: int64
4.0    508
5.0    283
3.0    167
2.0     46
1.0     30
NaN     10
Name: famrel, dtype: int64
1.0    719
2.0    194
3.0     69
5.0     26
4.0     26
NaN     10
Name: Dalc, dtype: int64
1.0    393
2.0    231
3.0    199
4.0    138
5.0     73
NaN     10
Name: Walc, dtype: int64
NaN    700
yes    175
no     169
Name: cheating, dtype: int64

Код Текст

0

famrel:  3.9361702127659575
Dalc:  1.4970986460348163
Walc:  2.2911025145067696


Код Текст

Основываясь на предыдующей работе, даатсет не содержит серьезных выбросов, способных крайне негативно повлиять на построение моделей


Категориальные признаки нужно привести к One-Hot-Encoded форме

Код Текст





Learning data


Ground Truth значения



Данные для обучения




Без G1 признака


Learning data features (no G1):  44

Лишние признаки & Feature eng.


Посмотрим какие признаки сильно коррелируют между собой, ведь это может ухудшить результаты обучения



Выведем признаки с высокой корреляцией

Код Текст

Pair                                                Cov
--------------------------------------------  ---------
('Medu', 'Fedu')                               0.642063
('Medu', 'is_Mjob_teacher')                    0.452952
('Dalc', 'Walc')                               0.626551
('is_Subject_Por', 'is_paid_no')               0.473453
('is_Mjob_services', 'is_Mjob_other')         -0.428556
('is_Fjob_services', 'is_Fjob_other')         -0.702118
('is_guardian_other', 'is_guardian_mother')   -0.416173
('is_guardian_mother', 'is_guardian_father')  -0.836005
('is_reason_reputation', 'is_reason_course')  -0.46711
('is_reason_home', 'is_reason_course')        -0.479456

Многие из коррелирующих признаков - взаимоисключающие one-hot encoded признаки и их изменять не стоит


Однако я обрачу внимание на взаимосвязь признаков Medu и Fedu, Dalc и Walc
В данном случае эти 4 признака можно свести к 2м путем объединения:

  • Medu + Fedu = Pedu (можно считать образование обоих родителей)
  • Walc + Dalc = Alc (учитываем общее пристрастие к алкоголю)



Split data



Код Текст

установлен random_state чтобы контролировать разбиение

Код Текст

Код Текст

Убедимся в правильности разбиения (в частности соотвествии y)

Код Текст



860    11
269     9
581     0
775    11
669     9
Name: G3, dtype: int64
Код Текст

Рассмотрим распределение G3 в выборках y_train и y_test

Код Текст

Код Текст

Мы можем видеть, что распределение G3 в y_train и y_test выборках одинаково

Код Текст

Scale data

Код Текст

Код Текст

Код Текст

Код Текст

Код Текст

Train shape:  (835, 43)
Example:
array([ 1.77837403, -0.72568138,  0.0362296 , -0.40926236,  0.05351395,
       -0.18409633, -1.8956647 , -1.77756101,  1.19804442, -0.03615913,
       -1.25268941,  0.61472578,  1.13199857, -0.61657545,  1.59787092,
       -2.72659924,  0.36042375, -0.80837203,  0.53534546,  1.00359929,
       -0.49437974, -0.3095166 , -0.50747426,  0.75468462,  1.90085761,
       -0.37303373, -0.79226278, -0.30718781, -0.48309685, -0.62583278,
       -0.25505102, -1.1430791 , -0.19962605,  4.23996141, -0.27573706,
        0.65558716, -0.54644333,  1.78773038, -0.34322668, -0.5925645 ,
       -0.81039869, -0.88058892,  1.00376842])
Код Текст

Test shape:  (209, 43)
Example:
array([ 0.20116499, -0.72568138,  0.0362296 , -0.40926236,  1.14337127,
        0.77068897, -1.01432838,  1.03887816, -0.70439696,  1.62279005,
       -1.25268941,  0.61472578, -0.88339334, -0.61657545, -0.62583278,
        0.36675724,  0.36042375, -0.80837203,  0.53534546, -0.99641362,
       -0.49437974, -0.3095166 ,  1.97054331,  0.75468462,  1.90085761,
       -0.37303373, -0.79226278, -0.30718781, -0.48309685,  1.59787092,
       -0.25505102, -1.1430791 , -0.19962605, -0.2358512 , -0.27573706,
       -1.5253502 ,  1.83001594,  1.78773038, -0.34322668, -0.5925645 ,
       -0.81039869,  0.63756335,  0.51016027])
Код Текст

Часть 2. Регрессия

Код Текст

  • Решите задачу регрессии: постройте модель, предсказывающую итоговую оценку, которую получит студент по предмету (G3). При решении задачи нельзя использовать признак G2.

  • Для решения задачи примените следующие методы:

    • Линейная регрессия + регуляризации
    • Полиномиальная регрессия
    • KNN
    • Деревья решений, Random Forest

    Для каждого метода выполните настройку гиперпараметров на кросс-валидации.

  • Оцените качество каждой модели на отложенной выборке, используйте различные метрики. Сравните модели и сделайте вывод о качестве решения задачи.

  • Задачу необходимо решить в двух вариантах: с использованием признака G1 и без него. Сравните качество решений в двух случаях.

  • В регрессионных моделях попробуйте дать интерпретацию весам признаков.


Код Текст

Код Текст






Linear regression

Код Текст


Losso CV



Alpha:  0.1
CPU times: user 248 ms, sys: 212 ms, total: 460 ms
Wall time: 242 ms

Test

Код Текст

SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │      13.6048   │    11.5461    │
├──────────┼────────────────┼───────────────┤
│ rmse     │       3.68847  │     3.39796   │
├──────────┼────────────────┼───────────────┤
│ mae      │       2.66373  │     2.41408   │
├──────────┼────────────────┼───────────────┤
│ medae    │       1.89809  │     1.70175   │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.116701 │     0.0880885 │
╘══════════╧════════════════╧═══════════════╛

WEIGHTS
G1                      0.295871
is_Subject_Math        -0.000000
is_paid_yes            -0.000000
is_famsup_yes           0.000000
is_schoolsup_yes       -0.000000
is_Pstatus_T           -0.000000
is_famsize_GT3         -0.000000
is_address_U            0.000000
is_sex_M               -0.000000
is_school_GP            0.000000
Pedu                    0.000000
is_nursery_yes          0.000000
absences               -0.000000
health                 -0.000000
goout                  -0.000000
freetime               -0.000000
famrel                  0.000000
failures               -0.000000
studytime               0.000000
traveltime             -0.000000
is_activities_yes       0.000000
is_higher_yes           0.000000
Alc                    -0.000000
is_Fjob_services       -0.000000
is_reason_home          0.000000
is_reason_other        -0.000000
is_reason_reputation    0.000000
is_reason_course       -0.000000
is_guardian_father      0.000000
is_guardian_other      -0.000000
is_guardian_mother     -0.000000
is_Fjob_other          -0.000000
is_Fjob_at_home        -0.000000
is_internet_yes         0.000000
is_Fjob_teacher         0.000000
is_Fjob_health          0.000000
is_Mjob_other          -0.000000
is_Mjob_services        0.000000
is_Mjob_at_home        -0.000000
is_Mjob_teacher         0.000000
is_Mjob_health          0.000000
is_romantic_yes        -0.000000
age                    -0.000000
dtype: float64

Метрики у модели очень слабые, а по весам можно видеть, что предсказание делается, основываясь только на G1 признаке - предыдущей оценке


No G1



Alpha:  29.900000000000002
CPU times: user 258 ms, sys: 223 ms, total: 481 ms
Wall time: 259 ms

Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       15.4023  │    13.0908    │
├──────────┼────────────────┼───────────────┤
│ rmse     │        3.92457 │     3.61813   │
├──────────┼────────────────┼───────────────┤
│ mae      │        2.8788  │     2.61368   │
├──────────┼────────────────┼───────────────┤
│ medae    │        2.21078 │     1.78922   │
├──────────┼────────────────┼───────────────┤
│ R2       │        0       │    -0.0339102 │
╘══════════╧════════════════╧═══════════════╛

WEIGHTS
Pedu                    0.0
is_school_GP            0.0
is_activities_yes       0.0
is_paid_yes            -0.0
is_famsup_yes          -0.0
is_schoolsup_yes       -0.0
is_Pstatus_T           -0.0
is_famsize_GT3         -0.0
is_address_U            0.0
is_sex_M               -0.0
is_Subject_Math        -0.0
Alc                    -0.0
absences               -0.0
health                 -0.0
goout                  -0.0
freetime               -0.0
famrel                  0.0
failures               -0.0
studytime               0.0
traveltime             -0.0
is_nursery_yes          0.0
is_higher_yes           0.0
is_internet_yes         0.0
is_romantic_yes        -0.0
is_reason_home          0.0
is_reason_other        -0.0
is_reason_reputation    0.0
is_reason_course       -0.0
is_guardian_father      0.0
is_guardian_other      -0.0
is_guardian_mother     -0.0
is_Fjob_other          -0.0
is_Fjob_services       -0.0
is_Fjob_at_home        -0.0
is_Fjob_teacher         0.0
is_Fjob_health          0.0
is_Mjob_other          -0.0
is_Mjob_services        0.0
is_Mjob_at_home        -0.0
is_Mjob_teacher         0.0
is_Mjob_health          0.0
age                    -0.0
dtype: float64

Убрав у модели G1 признак мы вовсе лешили ее возможности предсказывать - все веса равны нулю


Ridge CV

Код Текст


Alpha:  28.6
CPU times: user 5.68 s, sys: 7.22 s, total: 12.9 s
Wall time: 6.69 s
Код Текст

Test

Код Текст

SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       4.60432  │       4.91063 │
├──────────┼────────────────┼───────────────┤
│ rmse     │       2.14577  │       2.21599 │
├──────────┼────────────────┼───────────────┤
│ mae      │       1.42811  │       1.59266 │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.947277 │       1.27257 │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.701062 │       0.61216 │
╘══════════╧════════════════╧═══════════════╛

WEIGHTS
G1                      2.835659
is_Subject_Math        -0.618114
failures               -0.368477
health                 -0.228059
absences                0.218612
is_paid_yes             0.197687
is_romantic_yes        -0.196752
goout                  -0.176093
famrel                  0.158452
is_Pstatus_T           -0.135200
is_address_U            0.126000
is_higher_yes           0.116390
is_Mjob_health          0.109009
traveltime              0.093330
Alc                     0.088374
is_Mjob_services        0.074440
is_famsize_GT3         -0.072063
is_Fjob_services       -0.066631
is_Mjob_at_home        -0.060031
is_Mjob_other          -0.055127
is_reason_home         -0.054204
is_school_GP            0.053477
is_nursery_yes         -0.052833
is_Fjob_other           0.050603
is_reason_course        0.048157
is_schoolsup_yes        0.042978
freetime               -0.035239
is_internet_yes         0.034970
is_Mjob_teacher        -0.033365
is_guardian_father      0.032680
is_activities_yes      -0.028371
is_guardian_mother     -0.027458
is_sex_M                0.020741
is_Fjob_health          0.019942
is_Fjob_at_home         0.017033
Pedu                   -0.013755
age                    -0.012560
is_Fjob_teacher        -0.011470
studytime               0.010736
is_famsup_yes           0.006827
is_reason_other        -0.004952
is_guardian_other      -0.004532
is_reason_reputation    0.004077
dtype: float64

Данная линейная модель с Ridge регуляризацией показала хорошие результаты, судя по метрикам.

Также по весам можно понять, что модель использует все параметры для предсказания в разной мере.
Наиболее влияетельными оказались:

  • предыдущая оценка G1 (не удивительно)
  • предмет is_subject_Math (отрицательный вес показывает, что по математике оценка должны быть ниже)
  • прогулы failures (больше пропускаешь - оценка ниже)

No G1



Alpha:  29.900000000000002
CPU times: user 5.74 s, sys: 7.03 s, total: 12.8 s
Wall time: 6.62 s

Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │      10.704    │     11.0084   │
├──────────┼────────────────┼───────────────┤
│ rmse     │       3.2717   │      3.3179   │
├──────────┼────────────────┼───────────────┤
│ mae      │       2.38736  │      2.41881  │
├──────────┼────────────────┼───────────────┤
│ medae    │       1.72638  │      1.87332  │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.305035 │      0.130556 │
╘══════════╧════════════════╧═══════════════╛

WEIGHTS
failures               -1.065998
is_Subject_Math        -0.947771
is_higher_yes           0.482705
studytime               0.427825
is_schoolsup_yes       -0.393510
health                 -0.388848
is_school_GP            0.329083
goout                  -0.306595
is_Mjob_health          0.286244
is_romantic_yes        -0.273986
is_famsize_GT3         -0.247504
famrel                  0.239709
is_address_U            0.237777
is_famsup_yes          -0.231084
is_Fjob_teacher         0.221638
is_Mjob_other          -0.192995
is_Mjob_services        0.190275
is_Mjob_at_home        -0.157597
Pedu                    0.146618
Alc                    -0.137913
is_Fjob_services       -0.123705
is_paid_yes             0.116387
absences                0.114731
is_internet_yes         0.108024
is_nursery_yes         -0.100919
is_guardian_mother     -0.088158
is_guardian_other       0.077666
is_Pstatus_T           -0.073282
traveltime              0.055811
is_activities_yes       0.052456
freetime                0.051664
is_reason_reputation    0.051609
is_guardian_father      0.048765
age                    -0.042837
is_Fjob_at_home         0.042574
is_sex_M                0.035327
is_reason_other        -0.031182
is_reason_home         -0.021044
is_Fjob_other          -0.010299
is_Fjob_health         -0.009660
is_Mjob_teacher        -0.009414
is_reason_course       -0.006510
dtype: float64

Без признака G1 метрики стали сильно хуже, а большее влияение получили:

  • failures
  • is_higher_yes
  • studytime
Код Текст

Polynomial





CPU times: user 190 ms, sys: 50.9 ms, total: 241 ms
Wall time: 13.9 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('polynomialfeatures',
                                        PolynomialFeatures(degree=2,
                                                           include_bias=False,
                                                           interaction_only=False,
                                                           order='C')),
                                       ('linearregression',
                                        LinearRegression(copy_X=True,
                                                         fit_intercept=True,
                                                         n_jobs=None,
                                                         normalize=True))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'polynomialfeatures__degree': [1, 2, 3]},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_squared_error', verbose=0)

Best hyperparams


{'polynomialfeatures__degree': 1}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       4.63996  │      5.02588  │
├──────────┼────────────────┼───────────────┤
│ rmse     │       2.15406  │      2.24185  │
├──────────┼────────────────┼───────────────┤
│ mae      │       1.45921  │      1.62587  │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.973973 │      1.2604   │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.698748 │      0.603057 │
╘══════════╧════════════════╧═══════════════╛
Код Текст

Давайте убедимся в том, что выбранная степень полинома оптимальна.
Поставим degree=3 принудительно и сравним метрики


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │    1.79099e-28 │       7.14285 │
├──────────┼────────────────┼───────────────┤
│ rmse     │    1.33828e-14 │       2.67261 │
├──────────┼────────────────┼───────────────┤
│ mae      │    1.03539e-14 │       1.97092 │
├──────────┼────────────────┼───────────────┤
│ medae    │    8.88178e-15 │       1.54451 │
├──────────┼────────────────┼───────────────┤
│ R2       │    1           │       0.43586 │
╘══════════╧════════════════╧═══════════════╛

На метриках мы видим переобучение модели:

  • на x_train выборке все метрики показывает минимально возможную ошибку, значит наша модель смогла построить функцию, чтобы "попасть" во все точки датасета
  • на x_test выборке модель показывает плохую обобщающую способность, по крайней мере хуже обычной линейной модели

No G1


CPU times: user 130 ms, sys: 17.4 ms, total: 147 ms
Wall time: 10.6 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('polynomialfeatures',
                                        PolynomialFeatures(degree=2,
                                                           include_bias=False,
                                                           interaction_only=False,
                                                           order='C')),
                                       ('linearregression',
                                        LinearRegression(copy_X=True,
                                                         fit_intercept=True,
                                                         n_jobs=None,
                                                         normalize=True))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'polynomialfeatures__degree': [1, 2, 3]},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_squared_error', verbose=0)

{'polynomialfeatures__degree': 1}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │      10.698    │      11.1208  │
├──────────┼────────────────┼───────────────┤
│ rmse     │       3.27078  │       3.33479 │
├──────────┼────────────────┼───────────────┤
│ mae      │       2.39404  │       2.43725 │
├──────────┼────────────────┼───────────────┤
│ medae    │       1.73181  │       1.89116 │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.305429 │       0.12168 │
╘══════════╧════════════════╧═══════════════╛

Метрики сильно хуже моделей с G1 признаком


Давайте убедимся в том, что выбранная степень полинома оптимальна.
Поставим degree=3 принудительно и сравним метрики

Код Текст

SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │    2.20209e-28 │    13.0745    │
├──────────┼────────────────┼───────────────┤
│ rmse     │    1.48395e-14 │     3.61587   │
├──────────┼────────────────┼───────────────┤
│ mae      │    1.16314e-14 │     2.66703   │
├──────────┼────────────────┼───────────────┤
│ medae    │    8.88178e-15 │     2.05421   │
├──────────┼────────────────┼───────────────┤
│ R2       │    1           │    -0.0326215 │
╘══════════╧════════════════╧═══════════════╛

KNN

Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 1.7 s, sys: 41.2 ms, total: 1.74 s
Wall time: 12.2 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('kneighborsregressor',
                                        KNeighborsRegressor(algorithm='auto',
                                                            leaf_size=30,
                                                            metric='minkowski',
                                                            metric_params=None,
                                                            n_jobs=None,
                                                            n_neighbors=5, p=2,
                                                            weights='uniform'))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'kneighborsregr...
                                                            'brute'],
                         'kneighborsregressor__n_neighbors': array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]),
                         'kneighborsregressor__weights': ['uniform',
                                                          'distance']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_absolute_error', verbose=0)

{'kneighborsregressor__algorithm': 'ball_tree',
 'kneighborsregressor__n_neighbors': 26,
 'kneighborsregressor__weights': 'distance'}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │              0 │       8.46876 │
├──────────┼────────────────┼───────────────┤
│ rmse     │              0 │       2.91011 │
├──────────┼────────────────┼───────────────┤
│ mae      │              0 │       2.01901 │
├──────────┼────────────────┼───────────────┤
│ medae    │              0 │       1.42325 │
├──────────┼────────────────┼───────────────┤
│ R2       │              1 │       0.33114 │
╘══════════╧════════════════╧═══════════════╛

Так как KNN просто "запоминает" train выборку, то и метрики на ней наилучшие.
Однако на отложенных данных видим, что обобщающая способность далеко не лучшая


No G1


CPU times: user 2.04 s, sys: 70.9 ms, total: 2.11 s
Wall time: 12.5 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('kneighborsregressor',
                                        KNeighborsRegressor(algorithm='auto',
                                                            leaf_size=30,
                                                            metric='minkowski',
                                                            metric_params=None,
                                                            n_jobs=None,
                                                            n_neighbors=5, p=2,
                                                            weights='uniform'))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'kneighborsregr...
                                                            'brute'],
                         'kneighborsregressor__n_neighbors': array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]),
                         'kneighborsregressor__weights': ['uniform',
                                                          'distance']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_absolute_error', verbose=0)

{'kneighborsregressor__algorithm': 'ball_tree',
 'kneighborsregressor__n_neighbors': 26,
 'kneighborsregressor__weights': 'distance'}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │              0 │     10.6234   │
├──────────┼────────────────┼───────────────┤
│ rmse     │              0 │      3.25935  │
├──────────┼────────────────┼───────────────┤
│ mae      │              0 │      2.32431  │
├──────────┼────────────────┼───────────────┤
│ medae    │              0 │      1.6747   │
├──────────┼────────────────┼───────────────┤
│ R2       │              1 │      0.160968 │
╘══════════╧════════════════╧═══════════════╛

Без G1 параметра ожидаемо хуже
Также можно заметить, что grid.best_params_ такие же как и у моделей, обучаемых на выборке со всеми признаками


Random Forest


Код Текст

Код Текст


CPU times: user 11.8 s, sys: 766 ms, total: 12.6 s
Wall time: 10min 40s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('randomforestregressor',
                                        RandomForestRegressor(bootstrap=True,
                                                              ccp_alpha=0.0,
                                                              criterion='mse',
                                                              max_depth=None,
                                                              max_features='auto',
                                                              max_leaf_nodes=None,
                                                              max_samples=None,
                                                              min_impurity_decrease=0.0,
                                                              min_impurity_split=None,
                                                              min_samples_leaf=...
       189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
       202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
       215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
       228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
       241, 242, 243, 244, 245, 246, 247, 248, 249])},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_absolute_error', verbose=0)
Код Текст

{'randomforestregressor__max_features': 'auto',
 'randomforestregressor__n_estimators': 218}


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       0.597778 │      3.64406  │
├──────────┼────────────────┼───────────────┤
│ rmse     │       0.773161 │      1.90894  │
├──────────┼────────────────┼───────────────┤
│ mae      │       0.528149 │      1.38912  │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.380734 │      1.00459  │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.961189 │      0.712193 │
╘══════════╧════════════════╧═══════════════╛

Мы видим довольно сильное падение в качестве модели на test выборке
Можно поробовать избавиться от этого подобрав max_depth деревьев



GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('randomforestregressor',
                                        RandomForestRegressor(bootstrap=True,
                                                              ccp_alpha=0.0,
                                                              criterion='mse',
                                                              max_depth=None,
                                                              max_features='auto',
                                                              max_leaf_nodes=None,
                                                              max_samples=None,
                                                              min_impurity_decrease=0.0,
                                                              min_impurity_split=None,
                                                              min_samples_leaf=...
                                                              n_estimators=218,
                                                              n_jobs=None,
                                                              oob_score=False,
                                                              random_state=None,
                                                              verbose=0,
                                                              warm_start=False))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'randomforestregressor__max_depth': array([ 2,  4,  6,  8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34,
       36, 38, 40, 42, 44, 46, 48])},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_absolute_error', verbose=0)

{'randomforestregressor__max_depth': 6}


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       1.8317   │      3.59326  │
├──────────┼────────────────┼───────────────┤
│ rmse     │       1.3534   │      1.89559  │
├──────────┼────────────────┼───────────────┤
│ mae      │       1.00602  │      1.38352  │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.776568 │      1.05151  │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.881076 │      0.716205 │
╘══════════╧════════════════╧═══════════════╛

Получилось немного улучшить метрики


No G1




CPU times: user 6.3 s, sys: 454 ms, total: 6.75 s
Wall time: 5min 26s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('randomforestregressor',
                                        RandomForestRegressor(bootstrap=True,
                                                              ccp_alpha=0.0,
                                                              criterion='mse',
                                                              max_depth=None,
                                                              max_features='auto',
                                                              max_leaf_nodes=None,
                                                              max_samples=None,
                                                              min_impurity_decrease=0.0,
                                                              min_impurity_split=None,
                                                              min_samples_leaf=...
                         'randomforestregressor__n_estimators': array([150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174,
       176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200,
       202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226,
       228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248])},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='neg_mean_absolute_error', verbose=0)

{'randomforestregressor__max_features': 'auto',
 'randomforestregressor__n_estimators': 176}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       1.33962  │     10.6123   │
├──────────┼────────────────┼───────────────┤
│ rmse     │       1.15742  │      3.25765  │
├──────────┼────────────────┼───────────────┤
│ mae      │       0.8408   │      2.32433  │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.602273 │      1.60795  │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.913025 │      0.161843 │
╘══════════╧════════════════╧═══════════════╛

RandomForestRegressor, обученный на данных без признака G1 имеет плохую обобщающую способность




{'randomforestregressor__max_depth': 32}


Test


SCORES:
╒══════════╤════════════════╤═══════════════╕
│ metric   │   train scores │   test scores │
╞══════════╪════════════════╪═══════════════╡
│ mse      │       1.35514  │     10.7822   │
├──────────┼────────────────┼───────────────┤
│ rmse     │       1.1641   │      3.28363  │
├──────────┼────────────────┼───────────────┤
│ mae      │       0.842246 │      2.34461  │
├──────────┼────────────────┼───────────────┤
│ medae    │       0.614679 │      1.64679  │
├──────────┼────────────────┼───────────────┤
│ R2       │       0.912017 │      0.148425 │
╘══════════╧════════════════╧═══════════════╛

Улучшить результаты не получилось


Results

Код Текст


with G1


{'R2': 0.7162051857150782,
 'mae': 1.3835179330702032,
 'medae': 1.0515141031025337,
 'mse': 3.5932616642774806,
 'rmse': 1.895590057021159}

╒═══════════════╤══════════╤═════════╤═════════╤═════════╤═══════════╕
│ estimators    │      mse │    rmse │     mae │   medae │        R2 │
╞═══════════════╪══════════╪═════════╪═════════╪═════════╪═══════════╡
│ losso         │ 11.5461  │ 3.39796 │ 2.41408 │ 1.70175 │ 0.0880885 │
├───────────────┼──────────┼─────────┼─────────┼─────────┼───────────┤
│ ridge         │  4.91063 │ 2.21599 │ 1.59266 │ 1.27257 │ 0.61216   │
├───────────────┼──────────┼─────────┼─────────┼─────────┼───────────┤
│ poly          │  5.02588 │ 2.24185 │ 1.62587 │ 1.2604  │ 0.603057  │
├───────────────┼──────────┼─────────┼─────────┼─────────┼───────────┤
│ knn           │  8.46876 │ 2.91011 │ 2.01901 │ 1.42325 │ 0.33114   │
├───────────────┼──────────┼─────────┼─────────┼─────────┼───────────┤
│ random forest │  3.59326 │ 1.89559 │ 1.38352 │ 1.05151 │ 0.716205  │
╘═══════════════╧══════════╧═════════╧═════════╧═════════╧═══════════╛
Код Текст

Best Regression (G1)


model: RandomForestRegressor
params: n_estimators=218, max_depth=6
score (R2): 0.716


Код Текст

no G1


╒═══════════════╤═════════╤═════════╤═════════╤═════════╤════════════╕
│ estimators    │     mse │    rmse │     mae │   medae │         R2 │
╞═══════════════╪═════════╪═════════╪═════════╪═════════╪════════════╡
│ losso         │ 13.0908 │ 3.61813 │ 2.61368 │ 1.78922 │ -0.0339102 │
├───────────────┼─────────┼─────────┼─────────┼─────────┼────────────┤
│ ridge         │ 11.0084 │ 3.3179  │ 2.41881 │ 1.87332 │  0.130556  │
├───────────────┼─────────┼─────────┼─────────┼─────────┼────────────┤
│ poly          │ 13.0745 │ 3.61587 │ 2.66703 │ 2.05421 │ -0.0326215 │
├───────────────┼─────────┼─────────┼─────────┼─────────┼────────────┤
│ knn           │ 10.6234 │ 3.25935 │ 2.32431 │ 1.6747  │  0.160968  │
├───────────────┼─────────┼─────────┼─────────┼─────────┼────────────┤
│ random forest │ 10.8576 │ 3.29509 │ 2.35762 │ 1.62844 │  0.142469  │
╘═══════════════╧═════════╧═════════╧═════════╧═════════╧════════════╛
Код Текст

Best Regression (no G1)


model: KNeighborsRegressor
params: n_neighbors=26, algorithm="ball_tree", weights="distance"
score (R2): 0.16


Код Текст

Часть 3. Бинарная классификация

Код Текст

Решите задачу бинарной классификации: постройте модель, предсказывающую, сдаст студент предмет (G3 >= 8) или не сдаст (G3 < 8).
При решении задачи нельзя использовать признаки G1 и G2.

Код Текст

Уберем из использования G1

Код Текст

Код Текст

Создадим новый признак для предсказания

Код Текст

860    1
269    1
581    0
775    1
669    1
      ..
866    0
742    1
74     0
176    1
338    1
Name: G3, Length: 835, dtype: int64
Код Текст

Проверим распредление

Код Текст

Train:
1    0.894611
0    0.105389
Name: G3, dtype: float64
Test:
1    0.942584
0    0.057416
Name: G3, dtype: float64
Код Текст

Код Текст

Распределение практически одинаковое и не будет негавтино влиять на процесс обучения

Код Текст

Код Текст

Задание 1

  • Постройте дерево решений глубины 5 (остальные параметры по умолчанию), оцените качество на 5-fold валидации.
  • Для одного из деревьев (т.е. обученного на одной из итераций кросс-валидации) выведите само дерево - постройте график или выведите в текстовом виде. По структуре дерева сформулируйте правила, по которым принимается решение.
  • Сравните между собой деревья решений, полученных на различных итерациях 5-fold валидации. Сделайте вывод, насколько сильно они похожи или различаются между собой.
Код Текст

5-fold validation

Код Текст

CV MEAN SCORE:  0.8802395209580839
All scores:  0.862, 0.874, 0.868, 0.904, 0.892
Код Текст

Visualize


Код Текст

Код Текст

Код Текст

Compare trees

Код Текст

Задание 2

На кросс-валидации (5-fold из 2 повторений) оцените, как меняется качество модели Random Forest с ростом числа деревьев (при дефолтных значениях остальных параметров). Провизуализируйте результаты. Сколько деревьев достаточно в данном случае и почему?
NB: В сравнение включите конфигурацию, аналогичную простому дереву решений.

Код Текст

Код Текст

Код Текст

Код Текст

Код Текст

Код Текст

Код Текст


Вывод:
Основываясь на полученном графике оптимальное количество деревьев находится в районе 7-10


Код Текст

Задание 3

  • Настройте гиперпараметры модели Random Forest на 5-fold валдиации. В качестве метрики используйте F1-score. Замерьте время, затраченное на вычисления.
  • Обучите Random Forest с настроенными параметрами на всех данных для моделирования. На отложенной выборке оцените качество (F1-score) всего ансамбля и каждого дерева отдельно. Постройте график распределения качества деревьев в ансамбле и сравните результаты с качеством всего леса. Дайте комментарий.
  • Выведите важность признаков в Random Forest, сделайте выводы.
Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 3.19 s, sys: 134 ms, total: 3.33 s
Wall time: 47.9 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('randomforestclassifier',
                                        RandomForestClassifier(bootstrap=True,
                                                               ccp_alpha=0.0,
                                                               class_weight=None,
                                                               criterion='gini',
                                                               max_depth=None,
                                                               max_features='auto',
                                                               max_leaf_nodes=None,
                                                               max_samples=None,
                                                               min_impurity_decrease=0.0,
                                                               min_impurity_split=N...
                                                               warm_start=False))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'randomforestclassifier__criterion': ['gini',
                                                               'entropy'],
                         'randomforestclassifier__max_depth': [2, 3, 4, 5, 10,
                                                               15, None],
                         'randomforestclassifier__n_estimators': [1, 2, 3, 4, 5,
                                                                  6, 7, 8, 9,
                                                                  10, 12, 15,
                                                                  17, 20, 25,
                                                                  40, 75,
                                                                  100]},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1', verbose=0)
Код Текст

{'randomforestclassifier__criterion': 'entropy',
 'randomforestclassifier__max_depth': None,
 'randomforestclassifier__n_estimators': 20}
Код Текст

0.9474470250793129
Код Текст

RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
                       criterion='entropy', max_depth=None, max_features='auto',
                       max_leaf_nodes=None, max_samples=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=20,
                       n_jobs=None, oob_score=False, random_state=None,
                       verbose=0, warm_start=False)
Код Текст

F1:  0.9752475247524752
              precision    recall  f1-score   support

           0       1.00      0.17      0.29        12
           1       0.95      1.00      0.98       197

    accuracy                           0.95       209
   macro avg       0.98      0.58      0.63       209
weighted avg       0.95      0.95      0.94       209

Код Текст

0     0.918206
1     0.901333
2     0.938144
3     0.930591
4     0.936061
5     0.941176
6     0.929870
7     0.923483
8     0.934726
9     0.948980
10    0.932292
11    0.920213
12    0.940568
13    0.927461
14    0.938462
15    0.915789
16    0.927083
17    0.924282
18    0.927083
19    0.918635
dtype: float64
Код Текст

Код Текст


Вывод:
f1 score ансамбля - 0.975
f1 scores деревьев - большинство значений расположены в промежутке от 0.92-0.94

Каждое дерево по отдельности предсказывает результат хуже, чем в ансамбле.


Код Текст

Задание 4

  • Примените логистическую регрессию для решения задачи, подберите оптимальные значения гиперпараметров. Оцените качество (roc auc) на 5-fold валидации из 2 повторений.
  • Аналогично (на такой же валидации (тех же подвыборках) с такой же метрикой) оцените качество Random Forest с подобранными в предыдущем задании параметрами. Сравните с качеством логистическом регрессии.
  • Обучите логистическую модель с настроенными параметрами на всех данных для моделирования. На отложенной выборке оцените качество - постройте ROC-кривую, вычислите roc auc. Вычислите аналогичную метрику для Random Forest из Задания 3, сравните точность моделей.
Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 316 ms, sys: 25.6 ms, total: 342 ms
Wall time: 7.74 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('logisticregression',
                                        LogisticRegression(C=1.0,
                                                           class_weight=None,
                                                           dual=False,
                                                           fit_intercept=True,
                                                           intercept_scaling=1,
                                                           l1_ratio=None,
                                                           max_iter=1000,
                                                           multi_class='auto',
                                                           n_jobs=None,
                                                           penalty='l2',
                                                           random_state=None,
                                                           solver='lbfgs',
                                                           tol=0.0001,
                                                           verbose=0,
                                                           warm_start=False))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'logisticregression__class_weight': ['balanced', None],
                         'logisticregression__multi_class': ['ovr',
                                                             'multinomial'],
                         'logisticregression__solver': ['newton-cg', 'lbfgs',
                                                        'saga', 'sag',
                                                        'liblinear']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='roc_auc', verbose=0)
Код Текст

{'logisticregression__class_weight': None,
 'logisticregression__multi_class': 'ovr',
 'logisticregression__solver': 'liblinear'}
Код Текст

0.7545297976930533
Код Текст

Double 5-fold Validation

Код Текст

Logistic

Код Текст

Код Текст

0.7598481379128833
array([0.77568627, 0.78156863, 0.81058911, 0.70357942, 0.78001491,
       0.81686275, 0.68745098, 0.81319911, 0.68941089, 0.74011931])
Код Текст

Random Forest

Код Текст

Код Текст

0.7790725095407289
array([0.72117647, 0.82823529, 0.8264355 , 0.71290082, 0.80406413,
       0.84784314, 0.77490196, 0.65604027, 0.8310962 , 0.78803132])
Код Текст

Random Forest показывает результат немного лучше

Код Текст

Fully fitted

Код Текст

Код Текст

Код Текст

Код Текст


Вывод:
Random Forest покала себя лучше Logistic Regression
как на 5-fold валидации так и во время теста на отложенной выборке

RFC-ROC-AUC: 0.87
LR-ROC-AUC: 0.78


Код Текст

Задание 5

  • Используйте для решения задачи один из фреймворков градиентного бустинга: XGBoost, LightGDB или CatBoost.
  • Оцените на 5-fold валидации, как растет качество модели на обучающей и на тестовой выборках при добавлении каждого дерева. Провизуализируйте результаты.
  • Настройте гиперпараметры модели на 5-fold валидации, в качестве метрики используйте F1-score. Замерьте время, затраченное на вычисления.
  • Обучите модель с настроенными параметрами на всех данных для моделирования и оцените качество на отложенной выборке. Сравните результаты с другими моделями, дайте комментарий.
Код Текст

Код Текст

Код Текст

Рост количества деревьев

Код Текст

Код Текст

Код Текст

Значение f1-score практически не меняются от увеличения количества деревьев

Код Текст

Подбор параметров

Код Текст

Код Текст

Код Текст

CPU times: user 15.3 s, sys: 848 ms, total: 16.1 s
Wall time: 7min 20s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('xgbclassifier',
                                        XGBClassifier(base_score=0.5,
                                                      booster='gbtree',
                                                      colsample_bylevel=1,
                                                      colsample_bynode=1,
                                                      colsample_bytree=1,
                                                      gamma=0,
                                                      learning_rate=0.1,
                                                      max_delta_step=0,
                                                      max_depth=3,
                                                      min_child_weight=1,
                                                      missing=None,
                                                      n_estimators=100,
                                                      n_jobs...
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'xgbclassifier__gamma': [0, 1, 2, 5, 10],
                         'xgbclassifier__max_depth': array([ 1,  3,  5,  7,  9, 11, 13]),
                         'xgbclassifier__n_eta': array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]),
                         'xgbclassifier__sampling_method': ['uniform',
                                                            'gradient_based']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1', verbose=0)
Код Текст

{'xgbclassifier__gamma': 0,
 'xgbclassifier__max_depth': 3,
 'xgbclassifier__n_eta': 0.0,
 'xgbclassifier__sampling_method': 'uniform'}
Код Текст

0.9529755437469822
Код Текст

F1 score: 0.9698492462311556
Код Текст

Код Текст

              precision    recall  f1-score   support

           0       0.50      0.33      0.40        12
           1       0.96      0.98      0.97       197

    accuracy                           0.94       209
   macro avg       0.73      0.66      0.68       209
weighted avg       0.93      0.94      0.94       209

Код Текст


Вывод:
XGBClassifier оказался лучше как Random Forest, так и Logistic Regression
Модель хорошо предсказывает оба класса, несмотря на низкий support

XGBC-ROC-AUC: 0.89
XGBC-F1: 0.97

RFC-ROC-AUC: 0.87
LR-ROC-AUC: 0.78


Код Текст

Часть 4. Многоклассовая классификация

  • Решите задачу многоклассовой классификации: постройте модель, пресдказывающую оценку студента по предмету по 4 балльной шкале

    • Отлично: 18 <= G3 <= 20
    • Хорошо: 14 <= G3 <= 17
    • Удовлетворительно: 8 <= G3 <= 13
    • Неудовлетворительно: G3 < 8

    При решении задачи нельзя использовать признаки G1 и G2.

  • Для решения задачи примените следующие методы:

    • KNN
    • Логистическая регрессия
    • Деревья решений
    • Random Forest
    • Gradient Boosting

    На кросс-валидации подберите оптимальные значения гиперпараметров алгоритмов.

  • Оцените качество моделей, используйте confusion matrix и производные от нее метрики. Сделайте выводы.
Код Текст

Prepare labels

Код Текст

Целевая переменная будет представлена следующими классами:

  • 0 - Отлично
  • 1 - Хорошо
  • 2 - Удовлетворительно
  • 3 - Неудовлетворительно
Код Текст

Код Текст

860    2
269    2
581    3
775    2
669    2
      ..
866    3
742    2
74     3
176    1
338    2
Name: G3, Length: 835, dtype: int64
Код Текст

640    1
722    1
914    2
731    2
688    2
      ..
233    2
794    2
898    3
416    2
870    1
Name: G3, Length: 209, dtype: int64
Код Текст

Убираем G1 признак

Код Текст

Код Текст

Рассмотрим распределение G3 в выборках y_train и y_test

Код Текст

Код Текст

Мы можем видеть, что распределение G3 в y_train и y_test выборках одинаково

Код Текст

Код Текст

Код Текст

Код Текст


KNN

Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 2.77 s, sys: 122 ms, total: 2.9 s
Wall time: 21.7 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('kneighborsclassifier',
                                        KNeighborsClassifier(algorithm='auto',
                                                             leaf_size=30,
                                                             metric='minkowski',
                                                             metric_params=None,
                                                             n_jobs=None,
                                                             n_neighbors=5, p=2,
                                                             weights='uniform'))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'kneighborscl...
                                                             'kd_tree',
                                                             'brute'],
                         'kneighborsclassifier__n_neighbors': array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]),
                         'kneighborsclassifier__weights': ['uniform',
                                                           'distance']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1_weighted', verbose=0)
Код Текст

{'kneighborsclassifier__algorithm': 'ball_tree',
 'kneighborsclassifier__n_neighbors': 3,
 'kneighborsclassifier__weights': 'distance'}
Код Текст

Код Текст

TRAIN:
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        29
           1       1.00      1.00      1.00       199
           2       1.00      1.00      1.00       519
           3       1.00      1.00      1.00        88

    accuracy                           1.00       835
   macro avg       1.00      1.00      1.00       835
weighted avg       1.00      1.00      1.00       835


TEST:
              precision    recall  f1-score   support

           0       0.50      0.17      0.25         6
           1       0.54      0.52      0.53        60
           2       0.76      0.80      0.78       131
           3       0.18      0.17      0.17        12

    accuracy                           0.67       209
   macro avg       0.50      0.41      0.43       209
weighted avg       0.65      0.67      0.66       209

Код Текст

Код Текст

Так как KNN запоминает всю train выборку, то и оценки на ней будут максимальные.

Если же смотреть на результаты предсказания на test выборке,
то видна главная проблема - классы 0 и 1, у которых низкий
support (количество примеров, представлоенных в выборке),
ожидаемо предсказываются хуже, из за чего портится общая оценка классификатора.

Код Текст

Логистическая регрессия


Код Текст

Код Текст

Код Текст

CPU times: user 556 ms, sys: 116 ms, total: 672 ms
Wall time: 16.5 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('logisticregression',
                                        LogisticRegression(C=1.0,
                                                           class_weight=None,
                                                           dual=False,
                                                           fit_intercept=True,
                                                           intercept_scaling=1,
                                                           l1_ratio=None,
                                                           max_iter=1000,
                                                           multi_class='auto',
                                                           n_jobs=None,
                                                           penalty='l2',
                                                           random_state=None,
                                                           solver='lbfgs',
                                                           tol=0.0001,
                                                           verbose=0,
                                                           warm_start=False))],
                                verbose=False),
             iid='deprecated', n_jobs=-1,
             param_grid={'logisticregression__class_weight': ['balanced', None],
                         'logisticregression__multi_class': ['ovr',
                                                             'multinomial'],
                         'logisticregression__solver': ['newton-cg', 'lbfgs',
                                                        'saga', 'sag']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1_weighted', verbose=0)
Код Текст

{'logisticregression__class_weight': None,
 'logisticregression__multi_class': 'ovr',
 'logisticregression__solver': 'newton-cg'}
Код Текст

Код Текст

TRAIN:
              precision    recall  f1-score   support

           0       1.00      0.03      0.07        29
           1       0.56      0.43      0.49       199
           2       0.71      0.88      0.79       519
           3       0.70      0.30      0.42        88

    accuracy                           0.68       835
   macro avg       0.74      0.41      0.44       835
weighted avg       0.68      0.68      0.65       835


TEST:
              precision    recall  f1-score   support

           0       0.00      0.00      0.00         6
           1       0.56      0.38      0.46        60
           2       0.70      0.84      0.76       131
           3       0.33      0.25      0.29        12

    accuracy                           0.65       209
   macro avg       0.40      0.37      0.38       209
weighted avg       0.62      0.65      0.62       209

Код Текст

Код Текст

Предсказания классов с низким support свойтсвенно также как и KNN, однако в этот раз класс 0 не предсказывается вовсе - все метрики равны нулю.

Код Текст

Деревья решений

Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 6.76 s, sys: 94 ms, total: 6.85 s
Wall time: 19.1 s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('decisiontreeclassifier',
                                        DecisionTreeClassifier(ccp_alpha=0.0,
                                                               class_weight=None,
                                                               criterion='gini',
                                                               max_depth=None,
                                                               max_features=None,
                                                               max_leaf_nodes=None,
                                                               min_impurity_decrease=0.0,
                                                               min_impurity_split=None,
                                                               min_samples_leaf=1,
                                                               min_samples...
                         'decisiontreeclassifier__max_depth': [2, 3, 4, 5, 10,
                                                               12, 15, 17, 20,
                                                               30, None],
                         'decisiontreeclassifier__max_features': ['auto',
                                                                  'sqrt',
                                                                  'log2'],
                         'decisiontreeclassifier__min_samples_split': array([2, 3, 4, 5, 6, 7, 8, 9]),
                         'decisiontreeclassifier__random_state': [13],
                         'decisiontreeclassifier__splitter': ['best',
                                                              'random']},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1_weighted', verbose=0)
Код Текст

{'decisiontreeclassifier__criterion': 'gini',
 'decisiontreeclassifier__max_depth': 12,
 'decisiontreeclassifier__max_features': 'auto',
 'decisiontreeclassifier__min_samples_split': 4,
 'decisiontreeclassifier__random_state': 13,
 'decisiontreeclassifier__splitter': 'random'}
Код Текст

Код Текст

TRAIN:
              precision    recall  f1-score   support

           0       0.59      0.45      0.51        29
           1       0.75      0.55      0.63       199
           2       0.80      0.94      0.86       519
           3       0.91      0.58      0.71        88

    accuracy                           0.79       835
   macro avg       0.76      0.63      0.68       835
weighted avg       0.79      0.79      0.78       835


TEST:
              precision    recall  f1-score   support

           0       0.00      0.00      0.00         6
           1       0.56      0.48      0.52        60
           2       0.72      0.75      0.73       131
           3       0.12      0.17      0.14        12

    accuracy                           0.62       209
   macro avg       0.35      0.35      0.35       209
weighted avg       0.62      0.62      0.61       209

Код Текст

Код Текст

Снова видим нулевые метрики для 0 класса

Код Текст

Random Forest

Код Текст

Код Текст

Код Текст

Код Текст

CPU times: user 10.7 s, sys: 704 ms, total: 11.4 s
Wall time: 5min 28s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('randomforestclassifier',
                                        RandomForestClassifier(bootstrap=True,
                                                               ccp_alpha=0.0,
                                                               class_weight=None,
                                                               criterion='gini',
                                                               max_depth=None,
                                                               max_features='auto',
                                                               max_leaf_nodes=None,
                                                               max_samples=None,
                                                               min_impurity_decrease=0.0,
                                                               min_impurity_split=N...
             iid='deprecated', n_jobs=-1,
             param_grid={'randomforestclassifier__max_depth': [2, 3, 4, 5, 10,
                                                               15, 20, 30, 50,
                                                               None],
                         'randomforestclassifier__n_estimators': array([ 50,  55,  60,  65,  70,  75,  80,  85,  90,  95, 100, 105, 110,
       115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175,
       180, 185, 190, 195])},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1_weighted', verbose=0)
Код Текст

{'randomforestclassifier__max_depth': 30,
 'randomforestclassifier__n_estimators': 65}
Код Текст

Код Текст

TRAIN:
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        29
           1       1.00      1.00      1.00       199
           2       1.00      1.00      1.00       519
           3       1.00      1.00      1.00        88

    accuracy                           1.00       835
   macro avg       1.00      1.00      1.00       835
weighted avg       1.00      1.00      1.00       835


TEST:
              precision    recall  f1-score   support

           0       0.00      0.00      0.00         6
           1       0.56      0.38      0.46        60
           2       0.71      0.89      0.79       131
           3       0.50      0.17      0.25        12

    accuracy                           0.67       209
   macro avg       0.44      0.36      0.37       209
weighted avg       0.64      0.67      0.64       209

Код Текст

Код Текст

Судя по оценкам, полученным на train выборке, модель переобучилась.
Однако после эксперементов с гиперпараметрами выяснилось, что `testz метрики данной модели лучше.

Код Текст

Gradient Boosting

Код Текст

Код Текст

Код Текст


CPU times: user 23.1 s, sys: 2.47 s, total: 25.5 s
Wall time: 57min 27s
GridSearchCV(cv=KFold(n_splits=5, random_state=None, shuffle=True),
             error_score=nan,
             estimator=Pipeline(memory=None,
                                steps=[('gradientboostingclassifier',
                                        GradientBoostingClassifier(ccp_alpha=0.0,
                                                                   criterion='friedman_mse',
                                                                   init=None,
                                                                   learning_rate=0.1,
                                                                   loss='deviance',
                                                                   max_depth=3,
                                                                   max_features=None,
                                                                   max_leaf_nodes=None,
                                                                   min_impurity_decrease=0.0,
                                                                   min_impurity_sp...
                         'gradientboostingclassifier__loss': ['deviance',
                                                              'exponential'],
                         'gradientboostingclassifier__max_features': ['auto',
                                                                      'sqrt',
                                                                      'log2'],
                         'gradientboostingclassifier__n_estimators': array([ 50,  55,  60,  65,  70,  75,  80,  85,  90,  95, 100, 105, 110,
       115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175,
       180, 185, 190, 195])},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring='f1_weighted', verbose=0)
Код Текст

{'gradientboostingclassifier__criterion': 'mse',
 'gradientboostingclassifier__loss': 'deviance',
 'gradientboostingclassifier__max_features': 'log2',
 'gradientboostingclassifier__n_estimators': 145}
Код Текст

Код Текст

TRAIN:
              precision    recall  f1-score   support

           0       1.00      0.62      0.77        29
           1       0.87      0.78      0.82       199
           2       0.88      0.97      0.92       519
           3       0.97      0.72      0.82        88

    accuracy                           0.88       835
   macro avg       0.93      0.77      0.83       835
weighted avg       0.89      0.88      0.88       835


TEST:
              precision    recall  f1-score   support

           0       0.00      0.00      0.00         6
           1       0.51      0.38      0.44        60
           2       0.72      0.85      0.78       131
           3       0.33      0.25      0.29        12

    accuracy                           0.66       209
   macro avg       0.39      0.37      0.38       209
weighted avg       0.62      0.66      0.63       209

Код Текст

Код Текст

Results

Код Текст

Код Текст

╒═══════════════════╤═══════════════════╤══════════════════════╤════════════════╤═══════════════════╤════════════╤═══════════════╤════════════╕
│ estimators        │   precision_macro │   precision_weighted │   recall_macro │   recall_weighted │   f1_macro │   f1_weighted │   accuracy │
╞═══════════════════╪═══════════════════╪══════════════════════╪════════════════╪═══════════════════╪════════════╪═══════════════╪════════════╡
│ knn               │          0.495268 │             0.654403 │       0.412882 │          0.665072 │   0.432901 │      0.656798 │   0.665072 │
├───────────────────┼───────────────────┼──────────────────────┼────────────────┼───────────────────┼────────────┼───────────────┼────────────┤
│ log-regression    │          0.397628 │             0.61656  │       0.368257 │          0.650718 │   0.375601 │      0.624299 │   0.650718 │
├───────────────────┼───────────────────┼──────────────────────┼────────────────┼───────────────────┼────────────┼───────────────┼────────────┤
│ decistion-tree    │          0.347667 │             0.615222 │       0.349523 │          0.617225 │   0.346783 │      0.614988 │   0.617225 │
├───────────────────┼───────────────────┼──────────────────────┼────────────────┼───────────────────┼────────────┼───────────────┼────────────┤
│ random-forest     │          0.443158 │             0.635816 │       0.358874 │          0.674641 │   0.37364  │      0.639717 │   0.674641 │
├───────────────────┼───────────────────┼──────────────────────┼────────────────┼───────────────────┼────────────┼───────────────┼────────────┤
│ gradient-boosting │          0.391306 │             0.617649 │       0.370165 │          0.655502 │   0.375689 │      0.630413 │   0.655502 │
╘═══════════════════╧═══════════════════╧══════════════════════╧════════════════╧═══════════════════╧════════════╧═══════════════╧════════════╛
Код Текст

Best Multiclass Classifier

Выводы:
результаты обучения всех моделей сильно зависит от
набора данных и распределения целевых значений в нем
Способность предсказывать конкретный класс уменьшается с уменьшием
встречающихся примеров (support), иногда вовсе до нуля

Среди обученных моделей я бы выделил KNN и Random Forest.
Данные модели показали наилучшие метрики (accuracy + f1).

Однако KNN с преимуществом над RF определяет нулевой класс с крайне низким support.


model: RandomForestRegressor
params: n_estimators=65, max_depth=30 score (accuracy/f1): 0.67 / 0/64


model: KNeighborsClassifier
params: algorithm='ball_tree', n_neighbors=3, weights='distance'
score (accuracy/f1): 0.66 / 0/66

Код Текст